<script setup lang="ts">
import { TableColumnsType } from "ant-design-vue";
import { onMounted, watch, ref, nextTick, onBeforeUnmount } from "vue";
import VueJsonPretty from "vue-json-pretty";
import { type EdgeOptions, Graph } from "@antv/g6";
import type { NodeOptions } from "@antv/g6/src/spec/element/node.ts";

const dagContainer = ref<HTMLElement | null>(null);
let graph: Graph = null;

type TableDataType = {
  key: number,
  pattern_name: string,
  cybertwin_label: string,
  pattern_graph: string,
  analyse_time: string,
  invoke_time: string,
}

const props = defineProps<{
  result: TableDataType[]
}>();

const modalDataItem = ref<TableDataType>({} as TableDataType);
const modalOpen = ref<boolean>(false);

const columns: TableColumnsType<TableDataType>[] = [
  {
    title: '配置名称',
    dataIndex: 'pattern_name',
    key: 'pattern_name',
  },
  {
    title: '网络孪生标识',
    dataIndex: 'cybertwin_label',
    key: 'cybertwin_label',
  },
  {
    title: '微服务调用链',
    dataIndex: 'pattern_graph',
    key: 'pattern_graph',
  },
  {
    title: '分析时间',
    dataIndex: 'analyse_time',
    key: 'analyse_time',
  },
  {
    title: '触发时间',
    dataIndex: 'invoke_time',
    key: 'invoke_time',
  }
]

const showPatternDetail = (record: TableDataType) => {
  const pattern = JSON.parse(record.pattern_graph);
  modalDataItem.value = record;
  openModal()
  // console.log('Pattern Detail:', pattern);
}

const openModal = () => {
  modalOpen.value = true;
}

const closeModal = () => {
  modalOpen.value = false;
}

// watch(
//     () => props.result,
//     (newVal) => {
//       console.log(newVal);
//     },
//     { immediate: true }
// );

const constructGraphData = (pattern: string) => {
  try {
    const parsedPattern = JSON.parse(pattern);
    const nodes = parsedPattern.nodes.map((node: any) => ({
      id: node.id,
      data: {
        text: node.label,
      }
    }));
    const edges = parsedPattern.edges.map((edge: any) => ({
      source: edge.source,
      target: edge.target,
      label: edge.label, // 似乎没有用
    }));
    return { nodes, edges };
  } catch (e) {
    console.error('解析模式数据失败:', e);
    return { nodes: [], edges: [] };
  }
}


const renderDAG = () => {
  if (!dagContainer.value) return;

  try {
    // 如果之前已经创建了图表实例，先销毁它
    if (graph) {
      graph.destroy();
    }

    let { nodes, edges } = constructGraphData(modalDataItem.value.pattern_graph);

    // 写死的测试数据
    const graphData = {
      nodes: nodes,
      edges: edges
    }

    // 创建G6图实例
    graph = new Graph({
      container: dagContainer.value,
      width: dagContainer.value.offsetWidth,
      data: graphData,
      height: 360,
      layout: {
        type: 'dagre',
        rankdir: 'LR', // 水平方向布局，从左到右
        nodesep: 60,
        ranksep: 80
      },
      node: <NodeOptions>{
        type: 'rect',
        style: {
          size: [120, 60],
          radius: 6,
          stroke: '#40a9ff',
          fill: '#e6f7ff',
          lineWidth: 2,
          labelPlacement: 'center',
          labelText: (d) => {
            let svc = d.data.text.split("~")[0];
            let route = d.data.text.split("~")[1];
            // "服务: xxx \n endpoint: xxx"
            return `服务: ${svc} \n 方法: ${route}`;
          },
          labelWordWrap: true,
          labelMaxLines: 2,
          labelMaxWidth: '90%',
          labelBackground: true,
          labelBackgroundFill: '#eee',
          labelBackgroundFillOpacity: 0.5,
          labelBackgroundRadius: 4,
          labelPointerEvents: 'none',
          labelBackgroundPointerEvents: 'none',
          // shadowColor: '#ccc',
          // shadowBlur: 10,
          // shadowOffsetX: 0,
          // shadowOffsetY: 0,
        }
      },
      edge: <EdgeOptions>{
        // type: 'polyline',
        style: {
          radius: 10,
          endArrow: true,
          lineWidth: 2,
          stroke: '#1890ff',
          labelText: (d) => {
            return d.label.split(' ')[0];
          },
          labelWordWrap: true,
          labelTextBaseline: 'bottom',
          labelDx: -8,
          labelFontSize: 12,
          labelFontWeight: 'bold',
          labelFill: '#1890ff',
          labelBackgroundStroke: '#9ec9ff',
          labelBackgroundRadius: 2,
        },
      },

      behaviors: ['drag-canvas', 'drag-element']
    });

    graph.render();

    // 自适应布局
    graph.fitView(20);
  } catch (error) {
    console.error('渲染DAG图出错：', error);
  }
};

// 监听窗口大小变化，重新渲染图表
const resizeHandler = () => {
  if (graph && dagContainer.value) {
    graph.changeSize(dagContainer.value.offsetWidth, 360);
    graph.fitView(20);
  }
};

// 监听modelDataItem的变化，重新渲染DAG图
watch(() => modalOpen.value, (newVal) => {
  if (newVal) {
    nextTick(() => {
      renderDAG();
    });
  }
});

onMounted(() => {
  window.addEventListener('resize', resizeHandler);
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', resizeHandler);
  if (graph) {
    graph.destroy();
  }
});

</script>

<template>
  <div style="margin-left: 10px">
    <a-table :data-source="props.result" :columns="columns">
      <template #bodyCell="{column, text, record}">
        <template v-if="column.dataIndex === 'pattern_graph'">
          <a-popover>
            <template #content>
              <a @click="() => showPatternDetail(record)">点击查看详情</a>
            </template>
            {{ text.substring(0, 75) }}...
          </a-popover>

        </template>
      </template>
    </a-table>
    <a-modal v-model:open="modalOpen" title="配置详情" width="1024px" @ok="closeModal">
      <p>名称: {{ modalDataItem.pattern_name }}</p>
      <div style="background-color: #ececec; padding: 20px">
        详情:
        <a-row :gutter="10">
          <a-col :span="12">
            <a-card :bordered="false" style="height: 400px; overflow-y: auto">
              <VueJsonPretty
                  :data="JSON.parse(modalDataItem.pattern_graph)"
                  :style="{ height: '400px', overflowY: 'auto' }"/>
            </a-card>
          </a-col>
          <a-col :span="12">
            <a-card :bordered="false" title="DAG图" style="height: 400px">
              <div ref="dagContainer" style="width: 100%; height: 360px;"></div>
            </a-card>
          </a-col>
        </a-row>
      </div>
    </a-modal>
  </div>
</template>

<style scoped>

</style>
